package com.knowledge.business.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.aliyun.searchplat20240529.models.GetDocumentSplitResponseBody;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.knowledge.business.config.SiliconFlowConfig;
import com.knowledge.business.util.SiliconFlowEmbeddingUtil;
import com.knowledge.common.utils.AliYunDocumentSplitUtils;
import com.knowledge.common.utils.DateUtils;
import com.knowledge.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.knowledge.business.mapper.KnowledgeDocumentSegmentMapper;
import com.knowledge.business.domain.KnowledgeDocumentSegment;
import com.knowledge.business.service.IKnowledgeDocumentSegmentService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 文档分段Service业务层处理
 *
 * @author zhaoyk
 * @date 2025-09-14
 */
@Service
public class KnowledgeDocumentSegmentServiceImpl extends ServiceImpl<KnowledgeDocumentSegmentMapper, KnowledgeDocumentSegment> implements IKnowledgeDocumentSegmentService {
    @Autowired
    private KnowledgeDocumentSegmentMapper knowledgeDocumentSegmentMapper;

    @Autowired
    private SiliconFlowEmbeddingUtil siliconFlowEmbeddingUtil;

    @Autowired
    private SiliconFlowConfig siliconFlowConfig;


    // 默认特殊字符分隔符集合（可根据需求扩展）
    private static final Set<Character> DEFAULT_SEPARATORS = Set.of('$');

    /**
     * 查询文档分段
     *
     * @param id 文档分段主键
     * @return 文档分段
     */
    @Override
    public KnowledgeDocumentSegment selectKnowledgeDocumentSegmentById(String id) {
        return knowledgeDocumentSegmentMapper.selectKnowledgeDocumentSegmentBySegmentId(id);
    }

    /**
     * 对文档内容进行分段处理
     *
     * @param documentId      文档ID
     * @param documentContent 文档内容
     * @return 分段列表
     */
    @Override
    @Transactional
    public List<KnowledgeDocumentSegment> segmentDocumentContent(String documentId, String documentType, String documentContent) throws Exception {
        //先删除原来的数据
        QueryWrapper<KnowledgeDocumentSegment> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("document_id", documentId);
        knowledgeDocumentSegmentMapper.delete(queryWrapper);
        List<KnowledgeDocumentSegment> segments = new ArrayList<>();
        if (StringUtils.isEmpty(documentContent)) {
            return segments;
        }
        // 这里调用AliYunDocumentSplitUtils对文件档分片
        List<GetDocumentSplitResponseBody.GetDocumentSplitResponseBodyResultChunks> ResultChunks = AliYunDocumentSplitUtils.splitDocument(documentContent, documentType);
        int segmentIndex = 1;
        for (int i = 0; i < ResultChunks.size(); i++) {
            GetDocumentSplitResponseBody.GetDocumentSplitResponseBodyResultChunks chunk = ResultChunks.get(i);
            String content = chunk.getContent();
            if (StringUtils.isNotBlank(content)) {
                KnowledgeDocumentSegment segment = new KnowledgeDocumentSegment();
                segment.setDocumentId(documentId);
                segment.setSegmentIndex(segmentIndex++);
                segment.setSegmentContent(content);
                segment.setWordCount(content.length());
                segment.setVectorStatus("0"); // 未处理
                segments.add(segment);
                this.save(segment);
            }
        }
        // 批量保存所有分
        return segments;

    }


    public List<KnowledgeDocumentSegment> segmentsWord(String documentContent, String documentId) {

        List<KnowledgeDocumentSegment> segments = new ArrayList<>();
        // 定义特殊分段字符：两个或更多换行符、分号、感叹号、问号等
//        String[] paragraphs = documentContent.split("[\\n\\r]{2,}|[;!?。！？]+");
        // 建议调整分段策略，避免在问答内容中间分割
        String[] paragraphs = documentContent.split("[\\n\\r]{2,}"); // 只按段落分割
        // 或者使用更智能的分割逻辑，识别问答对结构
        int segmentIndex = 1;
        final int MAX_SEGMENT_LENGTH = 500; // 最大分段长度

        for (String paragraph : paragraphs) {
            String trimmedParagraph = paragraph.trim();
            if (StringUtils.isNotBlank(trimmedParagraph)) {
                // 如果段落过长，进一步拆分
                if (trimmedParagraph.length() > MAX_SEGMENT_LENGTH) {
                    segments.addAll(splitLongParagraph(documentId, segmentIndex, trimmedParagraph, MAX_SEGMENT_LENGTH));
                    segmentIndex += segments.size();
                } else {
                    segments.add(createSegment(documentId, segmentIndex++, trimmedParagraph));
                }
            }
        }
        return segments;
    }

    public List<KnowledgeDocumentSegment> segmentsPdf(String documentContent, String documentId) {
        // 基于标记分割，保留标记与内容的绑定
        List<KnowledgeDocumentSegment> segments = new ArrayList<>();
        Pattern pattern = Pattern.compile("()");
        Matcher matcher = pattern.matcher(documentContent);
        int lastEnd = 0;
        int segmentIndex = 1;
        while (matcher.find()) {
            String mark = matcher.group(1); // 获取标记
            int start = matcher.start();
            // 处理上一个标记到当前标记之间的内容（若存在）
            if (start > lastEnd) {
                String preContent = documentContent.substring(lastEnd, start).trim();
                if (StringUtils.isNotBlank(preContent)) {
                    KnowledgeDocumentSegment segment = createSegment(documentId, segmentIndex++, preContent);
                    segments.add(segment);
                }
            }
            // 处理当前标记及后续内容（直到下一个标记）
            lastEnd = matcher.end();
            int nextMarkStart = documentContent.indexOf("🔶", lastEnd);
            String currentContent;
            if (nextMarkStart != -1) {
                currentContent = mark + documentContent.substring(lastEnd, nextMarkStart).trim();
                lastEnd = nextMarkStart;
            } else {
                currentContent = mark + documentContent.substring(lastEnd).trim();
            }
            if (StringUtils.isNotBlank(currentContent)) {
                KnowledgeDocumentSegment segment = createSegment(documentId, segmentIndex++, currentContent);
                segments.add(segment);
            }
        }
        return segments;
    }

    private List<KnowledgeDocumentSegment> splitPdfLongParagraph(String documentId, int startIndex, String content, int maxLength) {
        List<KnowledgeDocumentSegment> longSegments = new ArrayList<>();
        // 1. 提取开头的标记（必须保留在第一段）
        String mark = "";
        Matcher markMatcher = Pattern.compile("()").matcher(content);
        if (markMatcher.find()) {
            mark = markMatcher.group(1);
            content = content.substring(markMatcher.end()).trim(); // 内容部分
        }
        // 2. 按条款序号拆分（优先）
        List<String> subParts = new ArrayList<>();
        Matcher clauseMatcher = Pattern.compile("(?=\\d+\\. |[①-⑳])").matcher(content);
        int lastPos = 0;
        while (clauseMatcher.find()) {
            int pos = clauseMatcher.start();
            if (pos > lastPos) {
                subParts.add(content.substring(lastPos, pos).trim());
            }
            lastPos = pos;
        }
        // 补充最后一部分
        if (lastPos < content.length()) {
            subParts.add(content.substring(lastPos).trim());
        }
        // 3. 若拆分后的子部分仍过长，按长度拆分
        int currentIndex = startIndex;
        for (String subPart : subParts) {
            if (subPart.length() <= maxLength) {
                // 拼接标记，创建分段
                String fullContent = mark + " " + subPart;
                longSegments.add(createSegment(documentId, currentIndex++, fullContent));
            } else {
                // 按长度拆分，确保每段不超过maxLength
                int partStart = 0;
                while (partStart < subPart.length()) {
                    int partEnd = Math.min(partStart + maxLength, subPart.length());
                    String partContent = mark + " " + subPart.substring(partStart, partEnd);
                    longSegments.add(createSegment(documentId, currentIndex++, partContent));
                    partStart = partEnd;
                }
            }
        }
        return longSegments;
    }


    /**
     * 拆分超长段落
     */
    private List<KnowledgeDocumentSegment> splitLongParagraph(String documentId, int startIndex, String content, int maxLength) {
        List<KnowledgeDocumentSegment> segments = new ArrayList<>();
        int index = startIndex;

        // 按句子拆分
        String[] sentences = content.split("[。！？.!?;；]");

        StringBuilder currentSegment = new StringBuilder();

        for (String sentence : sentences) {
            String fullSentence = sentence + "。";

            // 如果加上这句话会超出长度限制，先保存当前段落
            if (currentSegment.length() + fullSentence.length() > maxLength && currentSegment.length() > 0) {
                segments.add(createSegment(documentId, index++, currentSegment.toString().trim()));
                currentSegment = new StringBuilder();
            }

            // 如果单句话就很长，强制拆分
            if (fullSentence.length() > maxLength) {
                // 保存当前累积的内容
                if (currentSegment.length() > 0) {
                    segments.add(createSegment(documentId, index++, currentSegment.toString().trim()));
                    currentSegment = new StringBuilder();
                }

                // 强制按最大长度拆分长句子
                for (int i = 0; i < fullSentence.length(); i += maxLength) {
                    int end = Math.min(i + maxLength, fullSentence.length());
                    segments.add(createSegment(documentId, index++, fullSentence.substring(i, end)));
                }
            } else {
                currentSegment.append(fullSentence);
            }
        }

        // 保存剩余内容
        if (currentSegment.length() > 0) {
            segments.add(createSegment(documentId, index, currentSegment.toString().trim()));
        }

        return segments;
    }


    @Autowired
    VectorStorageService vectorStorageService;

    /**
     * 对分段内容进行向量化处理
     *
     * @param segment 分段对象
     * @return 向量数据
     */
    @Override
    public Boolean vectorizeSegmentContent(KnowledgeDocumentSegment segment) {
        String content = segment.getSegmentContent();
        if (StringUtils.isEmpty(content)) {
            return false;
        }
        try {
            // 调用硅基流动向量模型
            List<Float> vector = siliconFlowEmbeddingUtil.generateEmbedding(content);
            segment.setVectorModel(siliconFlowConfig.getModel());
            segment.setVectorStatus("1"); // 已处理
            // 更新数据库
            this.updateById(segment);
            // 直接存储到向量数据库（如Milvus）
            vectorStorageService.storeVector(segment, vector);
        } catch (Exception e) {
            e.printStackTrace();
            segment.setVectorStatus("2"); // 处理失败
            this.updateById(segment);
            return false;
        }
        return true;
    }


    /**
     * 创建分段对象
     *
     * @param documentId   文档ID
     * @param segmentIndex 分段序号
     * @param content      分段内容
     * @return 分段对象
     */
    private KnowledgeDocumentSegment createSegment(String documentId, int segmentIndex, String content) {
        KnowledgeDocumentSegment segment = new KnowledgeDocumentSegment();
        segment.setDocumentId(documentId);
        segment.setSegmentIndex(segmentIndex);
        segment.setSegmentContent(content);
        segment.setWordCount(content.length());
        segment.setVectorStatus("0"); // 未处理
        this.save(segment);
        return segment;
    }

    /**
     * 查询文档分段列表
     *
     * @param knowledgeDocumentSegment 文档分段
     * @return 文档分段
     */
    @Override
    public List<KnowledgeDocumentSegment> selectKnowledgeDocumentSegmentList(KnowledgeDocumentSegment knowledgeDocumentSegment) {
        return knowledgeDocumentSegmentMapper.selectKnowledgeDocumentSegmentList(knowledgeDocumentSegment);
    }

    /**
     * 新增文档分段
     *
     * @param knowledgeDocumentSegment 文档分段
     * @return 结果
     */
    @Override
    public int insertKnowledgeDocumentSegment(KnowledgeDocumentSegment knowledgeDocumentSegment) {
        knowledgeDocumentSegment.setCreateTime(DateUtils.getNowDate());
        return knowledgeDocumentSegmentMapper.insertKnowledgeDocumentSegment(knowledgeDocumentSegment);
    }

    /**
     * 修改文档分段
     *
     * @param knowledgeDocumentSegment 文档分段
     * @return 结果
     */
    @Override
    public int updateKnowledgeDocumentSegment(KnowledgeDocumentSegment knowledgeDocumentSegment) {
        knowledgeDocumentSegment.setUpdateTime(DateUtils.getNowDate());
        return knowledgeDocumentSegmentMapper.updateKnowledgeDocumentSegment(knowledgeDocumentSegment);
    }

    /**
     * 批量删除文档分段
     *
     * @param ids 需要删除的文档分段主键
     * @return 结果
     */
    @Override
    public int deleteKnowledgeDocumentSegmentByIds(String[] ids) {
        return knowledgeDocumentSegmentMapper.deleteKnowledgeDocumentSegmentByIds(ids);
    }

    /**
     * 删除文档分段信息
     *
     * @param id 文档分段主键
     * @return 结果
     */
    @Override
    public int deleteKnowledgeDocumentSegmentById(String id) {
        return knowledgeDocumentSegmentMapper.deleteKnowledgeDocumentSegmentById(id);
    }

    /**
     * 将byte数组转换为Float列表
     *
     * @param bytes byte数组
     * @return Float列表
     */
    @Override
    public List<Float> byteArrayToFloatList(byte[] bytes) {
        return siliconFlowEmbeddingUtil.byteArrayToFloatList(bytes);
    }
}
